package org.utils;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

@SuppressWarnings("unchecked")
public class PersistenceUtils<T, ID extends Serializable> extends HibernateDaoSupport {
	private Log logger = LogFactory.getLog(getClass());

	protected Class<T> entityClass;

	@SuppressWarnings("rawtypes")
	protected Class getEntityClass() {
		if (entityClass == null) {
			entityClass = (Class<T>) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0];
			logger.debug("T class = " + entityClass.getName());
		}
		return entityClass;
	}

	public T get(ID id) throws DataAccessException {
		T load = (T) getHibernateTemplate().get(getEntityClass(), id);
		return load;
	}

	public T load(ID id) throws DataAccessException {
		T load = (T) getHibernateTemplate().load(getEntityClass(), id);
		return load;
	}

	public void save(T t) throws DataAccessException {
	 	getHibernateTemplate().save(t);
	}
	
	public void saveOrUpdate(T t) throws DataAccessException {
	 	getHibernateTemplate().saveOrUpdate(t);
	}
    public  void delete(T t)throws DataAccessException{
    	getHibernateTemplate().delete(t);
    }
	
    public T query(T t){
		Query query = getSessionFactory().getCurrentSession().createQuery(getHQL(t));
		query.setFirstResult(0);
		query.setMaxResults(1);
		List<T> list = query.list();
		if (null != list && list.size() > 0) {
			return list.get(0);
		} else {
			return null;
		}
    }
    
    public List<T> queryList(T t,int startPos, int pageSize){
    	Query query = getSessionFactory().getCurrentSession().createQuery(getHQL(t));
    	query.setFirstResult(startPos);
		if (pageSize > 0) {
			query.setMaxResults(pageSize);
		}
		List<T> list = query.list();
		if (null != list && list.size() > 0) {
			return list;
		} else {
			return null;
		}
    }
    
    public int count(T t){
    	String hql = "select count(*)"+getHQL(t);
		Query query = getSessionFactory().getCurrentSession().createQuery(hql);
		Object object = query.uniqueResult();
		if(object==null){
			return 0;
		}else{
			return (int)((Long) object).longValue();
		}
    }
    
    public String getHQL(Object obj){
		Class<?> c = obj.getClass();
		String className = c.getSimpleName();
		StringBuffer cName = new StringBuffer(className.substring(0, 1).toLowerCase()+className.substring(1));
		Object object = obj;
		Method[] ms = c.getDeclaredMethods();
		StringBuffer hql=new StringBuffer("");
		for(Method m : ms){
			String fieldName = m.getName().substring(3, 4).toLowerCase()+ m.getName().substring(4);; 
			if(String.valueOf(m.getName()).substring(0,3).equals("get")){
				try {
					if(m.invoke(object)!=null&&!m.invoke(object).equals(0)){
						hql.append(cName).append(".").append(fieldName).append(" = '").append(m.invoke(object)).append("' and ");
					}
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		if(hql.length()>0){
			String condition = String.valueOf(hql).substring(0, hql.length()-4);
			hql = new StringBuffer(" from ").append(className).append(" ").append(cName).append(" where ").append(condition);
		}else{
			hql = new StringBuffer(" from ").append(className).append(" ").append(cName).append(" "); 
		}
		hql.append("order by ").append(cName).append(".id desc");
		return hql.toString();
    }
}
